package com.xxl.job.executor.my.service.impl;

import com.alibaba.fastjson.JSON;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.executor.my.entity.*;
import com.xxl.job.executor.my.mapper.querydb.BatchStockHandleMapper;
import com.xxl.job.executor.my.mapper.rangland.RangeLandMapper;
import com.xxl.job.executor.my.service.RangeLandService;
import com.xxl.job.executor.my.util.EsUtil;
import com.xxl.job.executor.my.util.MyDateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;


/**
 * <h3>xxl-job</h3>
 * <p>养猪管理系统业务处理</p>
 *
 * @author : 来朋
 * @date : 2020-12-19 17:24
 **/
@Service
public class RangeLandServiceImpl implements RangeLandService {

    @Autowired
    private RangeLandMapper rangeLandMapper;

    @Autowired
    private EsUtil esUtil;

    @Autowired
    private BatchStockHandleMapper batchStockHandleMapper;

    /**
     * 获取养猪系统的信息
     * @return
     */
    @Override
    public void adjustBathStock() {
        SimpleDateFormat dfFormat=new SimpleDateFormat("yyyy-MM-dd");
        for (Integer itmp=-2;itmp<=5;itmp++) {
            Date nowDate=new Date();
            try {
            String dateString = "2020-12-21";
            nowDate = dfFormat.parse(dateString);
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(nowDate);
                calendar.add(Calendar.DAY_OF_YEAR, (itmp));
                nowDate = calendar.getTime();
                System.out.println("业务日期："+dfFormat.format(nowDate));
            } catch (Exception err) {
                System.out.println("日期转换发生错误："+err.getMessage());
                XxlJobHelper.log("获取日期出现错误：\n" + err.getMessage() + "\n");
            }
            Boolean bContinue=true;
            Integer iPage=0,iEachPageRow=1000;
            while (bContinue) {
                List<BatchStockEntity> rangelandList = rangeLandMapper.getBatchStockList(iPage, iEachPageRow, nowDate);
                if (rangelandList != null && rangelandList.size() > 0) {
                    //获取ES中的信息
                    List<String> batchList = new ArrayList<>();
                    rangelandList.stream().forEach(batch -> batchList.add(batch.getBatchno()));
                    List<BatchStockEntity> batchStockESList = esUtil.queryBatchInfo(batchList, nowDate);
                    getDifferentInfo(rangelandList, batchStockESList);
                    //下一页处理
                    iPage = iPage + 1;
                } else {
                    bContinue = false;
                }
            }
        }
    }

    /**
     * 校正批次信息
     * @param rangelandList
     * @param esList
     */
    private void getDifferentInfo(List<BatchStockEntity> rangelandList,List<BatchStockEntity> esList) {
        try {
//            1、养猪存在、ES不存在要删除；
//            2、ES存在，养猪不存在要删除；
//            3、养猪和ES都存在要更新；
            if (esList.isEmpty()==false){
                esUtil.bulkDelete(esList);
                XxlJobHelper.log("批量删除"+esList.size()+"条数据成功！\n");
            }
            List<Map<String, Object>> insertList = new ArrayList<>();
            if (rangelandList!=null&&rangelandList.isEmpty()==false){
                rangelandList.stream().forEach(x->{
                    insertList.add(JSON.parseObject(JSON.toJSONString(x), Map.class));
                });
                esUtil.bulkInsert(insertList);
                XxlJobHelper.log("批量新增"+insertList.size()+"条数据成功！\n");
            }

//            if (rangelandList!=null&&rangelandList.size()>0&&esList!=null&&esList.size()>0){
                //ES数据比较准确的时候可以用对比的方法处理
//                List<BatchStockEntity> newEsList=new ArrayList<>();
//                //对ES去重
//                esList.parallelStream().filter(t->{
//                    Set<Object> seen = ConcurrentHashMap.newKeySet();
//                    return seen.add(t.getBatchno());
//                }).forEach(x->newEsList.add(x));
//                List<BatchStockEntity> addList = new ArrayList<>();
//                List<BatchStockEntity> delList=new ArrayList<>();
//                //比较ES信息
//                rangelandList.stream().forEach(rangeland->{
//                    BatchStockEntity batchStockEntity = newEsList.stream().filter(x -> x.getBatchno().equals(rangeland.getBatchno()))
//                            .findFirst().orElse(rangeland.setLivestock(0)
//                                                        .setDayold(0f)
//                                                        .setInqty(0)
//                                                        .setIndayold(0f)
//                                                        .setOutqty(0)
//                                                        .setOutdayold(0f));
//                    if (batchStockEntity!=null){
//                        if (rangeland.getLivestock().equals(batchStockEntity.getLivestock())==false
//                                || rangeland.getDayold().equals(batchStockEntity.getDayold())==false
//                                || rangeland.getInqty().equals(batchStockEntity.getInqty())==false
//                                || rangeland.getIndayold().equals(batchStockEntity.getIndayold())==false
//                                || rangeland.getOutqty().equals(batchStockEntity.getOutqty())==false
//                                || rangeland.getOutdayold().equals(batchStockEntity.getOutdayold())==false){
//                            delList.add(batchStockEntity);
//                        }
//                    } else{
//                        addList.add(rangeland);
//                    }
//                });
//                if (delList.isEmpty()==false){
//                    esUtil.bulkDelete(delList);
//                    XxlJobHelper.log("批量删除"+delList.size()+"条数据成功！\n");
//                }
//                List<Map<String, Object>> insertList = new ArrayList<>();
//                if (addList!=null&&addList.isEmpty()==false){
//                    addList.stream().forEach(x->{
//                        insertList.add(JSON.parseObject(JSON.toJSONString(x), Map.class));
//                    });
//                    esUtil.bulkInsert(insertList);
//                    XxlJobHelper.log("批量新增"+insertList.size()+"条数据成功！\n");
//                }
//            }
        } catch (Exception err){
            System.out.println("校正批次信息时发生异常:\n" + err.getMessage());
            XxlJobHelper.log("校正批次信息时发生异常:\n" + err.getMessage()+"\n");
        }

    }

/*
    1、获取要处理的异常批次信息
    2、计算每个批次从异常日期到当前日期的存栏和日龄，并向后计算10天
    3、获取省份、区域等基础信息
    4、更新养猪查询库的信息
    5、将该批次相关的异常信息标记为已处理 fflag=10
*/
    @Override
    @Transactional(value = "ds2TransactionManager",rollbackFor = Exception.class)
    public void handleBatchErrorLogOfQuerydb() {
        //1、获取要处理的异常批次信息
        List<BatchStockErrorEntity> batchMqErrorList = batchStockHandleMapper.getBatchMqErrorList();
        //2、获取批次中最小日期开始计算
        List<String> batchList=null;
        if (batchMqErrorList!=null&&batchMqErrorList.isEmpty()==false){
            //获取去重的批次信息
            batchList = batchMqErrorList.stream().map(BatchStockErrorEntity::getBatchno)
                    .distinct().collect(Collectors.toList());
        }
        if (batchList!=null&&batchList.isEmpty()==false){
            batchList.stream().forEach(x->{
                BatchStockErrorEntity stockErrorEntity = batchMqErrorList.stream()
                        .filter(errorlist -> errorlist.getBatchno().equals(x))
                        .distinct()
                        .min(Comparator.comparing(BatchStockErrorEntity::getFdate))
                        .get();
//                System.out.println(stockErrorEntity);
                if (stockErrorEntity!=null){
                    //计算每个批次从异常日期到当前日期的存栏和日龄，并向后计算10天
                    totalBatchQtyAndDayold(stockErrorEntity);
                }
            });
            //处理成功后将该批次相关的异常信息标记为已处理 fflag=10
            List<Integer> integerList = batchMqErrorList.stream().map(BatchStockErrorEntity::getFid)
                    .collect(Collectors.toList());
            batchStockHandleMapper.updateErrorLogState(integerList);
//                    System.out.println("更新成功："+integerList);
        }
    }

    /**
     * 计算批次存栏信息
     * @param batchStockErrorEntity
     */
    private void totalBatchQtyAndDayold(BatchStockErrorEntity batchStockErrorEntity){
        Date dLastDate = MyDateUtil.getLastDay(batchStockErrorEntity.getFdate());
        //获取批次截止当前日期前一天的存栏和日龄
//        System.out.println("日期："+dLastDate);
        List<Map<String, Object>> qtyAndDayolds = rangeLandMapper.getBatchQtyAndDayolds(
                batchStockErrorEntity.getBatchno(), dLastDate);
//        System.out.println(qtyAndDayolds);
        BatchQtyAndDayoldEntity batchQtyAndDayold = new BatchQtyAndDayoldEntity();
        if (qtyAndDayolds != null && qtyAndDayolds.isEmpty() == false) {
            batchQtyAndDayold.setQty(Integer.parseInt(qtyAndDayolds.get(0).get("FCount").toString()));
            batchQtyAndDayold.setDayold(Float.parseFloat(qtyAndDayolds.get(0).get("FDayOld").toString()));
        }
        //获取批次转群信息
        Date dNowDate = MyDateUtil.getNowDay(batchStockErrorEntity.getFdate());
        SimpleDateFormat dformat = new SimpleDateFormat("yyyy-MM-dd");
        List<BatchChgLogEntity> batchChgLogList = rangeLandMapper.getBatchChgLogList(
                batchStockErrorEntity.getBatchno(), dformat.format(dNowDate));
        //获取批次的省份、区域、分场等信息
        BatchInfoEntity batchInfo = rangeLandMapper.getBatchInfo(batchStockErrorEntity.getBatchno());
        //计算当前日期后300天批次的存栏和日龄
        List<BatchStockEntity> changeEntityList = handleBatchQtyAndDayold(batchQtyAndDayold, batchChgLogList,
                batchInfo, batchStockErrorEntity.getBatchno(), dNowDate);
        //更新批次存栏信息到养猪系统查询库
        if (changeEntityList!=null&&changeEntityList.isEmpty()==false) {
            totalBatchQty(changeEntityList);
        }
    }

    /**
     * 计算当前日期后300天批次的存栏和日龄
     * @param batchQtyAndDayoldEntity
     * @param batchChgLogEntityList
     * @return
     */
    private List<BatchStockEntity> handleBatchQtyAndDayold(BatchQtyAndDayoldEntity batchQtyAndDayoldEntity,
                                                            List<BatchChgLogEntity> batchChgLogEntityList,
                                                            BatchInfoEntity batchInfo,String strBatchNO,Date dNowDate){
        List<BatchStockEntity> listResult = new ArrayList<BatchStockEntity>();
        final Integer tmpQty=batchChgLogEntityList==null?0:batchQtyAndDayoldEntity.getQty();
        final Float tmpDayOld=batchChgLogEntityList==null?0f:batchQtyAndDayoldEntity.getDayold();
        //生成一次从当天日期到300天的set
        Date dNeedDate=MyDateUtil.addAndSubtractDaysByGetTime(dNowDate,12);
        Set<Date> dateSet=new TreeSet<Date>();
        while (dNowDate.equals(dNeedDate)==false){
            dateSet.add(dNowDate);
            dNowDate=MyDateUtil.addAndSubtractDaysByGetTime(dNowDate,1);
        }
//        System.out.println(strBatchNO);
        //计算每一天的存栏和日龄
        if (dateSet.isEmpty()==false&&batchChgLogEntityList.isEmpty()==false){
            dateSet.forEach(date -> {
                BatchChgLogEntity batchChgLogEntity = batchChgLogEntityList.stream().
                        filter(x -> x.getFdate().equals(date))
                        .findFirst()
                        .orElse((new BatchChgLogEntity()).setFdate(date)
                                .setInDayOld(0f).setInQty(0).setOutDayOld(0f).setOutQty(0));
                BatchStockEntity batch=new BatchStockEntity();
                batch.setProvince(batchInfo.getProvince())
                        .setArea(batchInfo.getArea())
                        .setField(batchInfo.getField())
                        .setSegment(batchInfo.getSegment())
                        .setFeeder(batchInfo.getFeeder())
                        .setBatchno(strBatchNO)
                        .setBatchstate(batchInfo.getBatchstate())
                        .setNowdate(date);
                BatchStockEntity tmpBatch = listResult.stream().filter(x -> x.getNowdate().equals(MyDateUtil.addAndSubtractDaysByGetTime(date,-1)))
                        .findFirst()
                        .orElse((new BatchStockEntity()).setLivestock(tmpQty).setDayold(tmpDayOld));
                //存栏、日龄计算
                Integer tmpStock=tmpBatch.getLivestock()+batchChgLogEntity.getInQty()-batchChgLogEntity.getOutQty();
                Float tmpBatchDayOld=((tmpBatch.getLivestock()+batchChgLogEntity.getInQty()-batchChgLogEntity.getOutQty())==0?0f:
                        ((tmpBatch.getLivestock()*(tmpBatch.getDayold()+1))
                                +batchChgLogEntity.getInDayOld() -batchChgLogEntity.getOutDayOld())
                                /(tmpBatch.getLivestock()+batchChgLogEntity.getInQty()-batchChgLogEntity.getOutQty()) );
                batch.setLivestock((tmpStock>0?tmpStock:0))
                        .setDayold(((tmpStock>0&&tmpBatchDayOld>0)?tmpBatchDayOld:0f))
                        .setInqty(0)
                        .setIndayold(0f)
                        .setOutqty(0)
                        .setOutdayold(0f);
                listResult.add(batch);
            });
        }
        return listResult;
    }

    /**
     * 计算批次存栏并同步到养猪系统查询库
     * @param list
     */
    public void totalBatchQty(List<BatchStockEntity> list) {
        batchStockHandleMapper.updateBatchQty(list);
    }



}
